import time
from collections import Counter, defaultdict
import random
import sys
from S_DES import *

def bin8(i):
    return format(i, '08b')

def bin10(i):
    return format(i, '010b')


# ---------- 1) 对固定明文统计密文出现次数 ----------
def stats_for_plain(plain_bin):
    """
    统计在所有 1024 个 key 下，fixed plaintext -> ciphertext 的计数分布
    返回 Counter
    """
    cnt = Counter()
    for k in range(1024):
        key_bin = bin10(k)
        des = S_DES_Binary(key_bin)
        des.Encryption(plain_bin)
        c = des.ciperText
        cnt[c] += 1
    vals = list(cnt.values())
    return cnt, min(vals), max(vals), sum(vals)/len(vals), len(vals)


# ---------- 2) 构造等价类：基于完整 256 明文字典映射 ----------
def build_full_mappings(save_progress=False,log=None):
    """
    为每个 key 计算完整的 256 个明文->密文 映射（以 tuple 顺序化），
    然后基于 mapping 分组密钥，返回 dict: mapping_tuple -> [keys...]
    """
    mapping_to_keys = defaultdict(list)
    t0 = time.perf_counter()
    for k in range(1024):
        key_bin = bin10(k)
        des = S_DES_Binary(key_bin)
        # 构造完整映射（顺序 0..255）
        mapping = []
        for p in range(256):
            pbin = bin8(p)
            # 每次调用 Encryption（该方法会设置 des.ciperText）
            des.Encryption(pbin)
            mapping.append(des.ciperText)
        mapping_tuple = tuple(mapping)
        mapping_to_keys[mapping_tuple].append(k)
        if save_progress and (k+1) % 128 == 0:
            if log is not None:
                log.emit(f"  进度：{k+1}/1024 个密钥已计算")
    t1 = time.perf_counter()
    print(f"已为 1024 个密钥构建全部映射，用时 {t1-t0:.2f} 秒")
    return mapping_to_keys


# ---------- 3) 检查等价类分布与差值 ----------
def analyze_equivalence_classes(mapping_to_keys):
    sizes = Counter(len(v) for v in mapping_to_keys.values())
    print("等价类大小分布：", dict(sizes))
    # 如果很多都是 size==2，检查差值
    diffs = set()
    for group in mapping_to_keys.values():
        if len(group) == 2:
            a, b = group
            diffs.add(a ^ b)
    return sizes, diffs


# ---------- 4) Monte-Carlo：给定 t 个 (P,C) 统计候选 key 数量 ----------
def count_candidates_for_pairs(pairs):
    """
    pairs: list of tuples (pbin, cbin)
    返回候选 key 列表
    """
    candidates = []
    for k in range(1024):
        key_bin = bin10(k)
        des = S_DES_Binary(key_bin)
        ok = True
        for pbin, cbin in pairs:
            des.Encryption(pbin)
            if des.ciperText != cbin:
                ok = False
                break
        if ok:
            candidates.append(k)
    return candidates

def monte_carlo_trial(trials=1000, t_values=(1,2,3,4,5,6),log = None):
    """
    对随机密钥做 trials 次实验：对每个试验
    - 随机挑一个 true_key
    - 生成 t random plaintexts, 得到对应 ciphertexts
    - 在全密钥空间中搜索满足所有 pairs 的候选 keys 个数
    返回每个 t 的统计（list of counts）
    """
    results = {t: [] for t in t_values}
    rng = random.Random(12345)
    for it in range(trials):
        true_k = rng.randrange(1024)
        key_bin = bin10(true_k)
        des_true = S_DES_Binary(key_bin)
        # 为效率：先生成 plaintexts and ciphertexts under true_k
        # 选 t_max plaintexts（不同的 p）
        tmax = max(t_values)
        ps = rng.sample(range(256), k=tmax)
        pcs = []
        for p in ps:
            pbin = bin8(p)
            des_true.Encryption(pbin)
            pcs.append((pbin, des_true.ciperText))
        # 对每个 t，取前 t 对进行候选搜索
        for t in t_values:
            pairs = pcs[:t]
            cand = count_candidates_for_pairs(pairs)
            results[t].append(len(cand))
        if (it+1) % 100 == 0:
            if log is not None:
                log.emit(f"MonteCarlo 进度：{it+1}/{trials}")
    # 计算统计量：平均、中位、最大
    stats = {}
    for t in t_values:
        arr = results[t]
        stats[t] = {
            'mean': sum(arr)/len(arr),
            'median': sorted(arr)[len(arr)//2],
            'max': max(arr),
            'hist_counter': Counter(arr)
        }
    return stats

if __name__=="__main__":
    name = input().strip()
    a = float(input())
    v = float(input())
    length = v * v / (2 * a)
    print(f"The acceleration of {name} is {a:.2f} M / s, the take-off speed is {v:.2f} M / s, and the shortest take-off runway length is {length:.2f} M. ")